namespace UmSoft.SharePoint.Integration._1Cv77
{
    using System;
    using System.Collections;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using UmSoft.SharePoint.Integration._1Cv77;

    public sealed class V7 : IComObject, IDisposable
    {

        internal const string IntegrationVariableName = "\"Интеграция\"";
        private bool isConnected;
        private object application;
        private string dbPath;
        private string userName;
        private string password;
        private bool trimString;
        private Hashtable activeObjects;
        public V7()
        {
            trimString = true;
            activeObjects = new Hashtable();
        }
        public void Connect(string userName, string password, string dbPath)
        {
            this.userName = userName;
            this.password = password;
            this.dbPath = dbPath;
            Type type = Type.GetTypeFromProgID("V77.Application");
            this.application = Activator.CreateInstance(type);
            this.isConnected = (bool)type.InvokeMember("Initialize", BindingFlags.InvokeMethod, null, this.application,
                new object[] {
                        type.InvokeMember("RMTrade", BindingFlags.GetProperty, null, this.application, null),
                        ConnectionString,
                        "NO_SPLASH_SHOW"});
        }
        public void Disconnect()
        {
            int i = 0;
            IDictionaryEnumerator idictionaryEnumerator = activeObjects.GetEnumerator();
            try
            {
                while (idictionaryEnumerator.MoveNext())
                {
                    DictionaryEntry dictionaryEntry = (DictionaryEntry)idictionaryEnumerator.Current;
                    object obj = dictionaryEntry.Value;
                    if (obj != null)
                        i = Marshal.FinalReleaseComObject(obj);
                    while (i > 0)
                    {
                        i = Marshal.FinalReleaseComObject(obj);
                    }
                }
            }
            finally
            {
                IDisposable idisposable = idictionaryEnumerator as IDisposable;
                if (idisposable != null)
                    idisposable.Dispose();
            }
            if (application != null)
            {
                i = Marshal.FinalReleaseComObject(application);
                while (i > 0)
                {
                    i = Marshal.FinalReleaseComObject(application);
                }
            }
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            isConnected = false;
        }
        public V7Object CreateObject(string aggregateTypeName)
        {
            return (((IComObject)this).InvokeMethod("CreateObject", new object[] { aggregateTypeName }) as V7Object);
        }
        public object EvalExpr(string expression)
        {
            return ((IComObject)this).InvokeMethod("EvalExpr", new object[] { expression });
        }
        public object GetConstant(string constantName)
        {
            object obj;
            obj = EvalExpr(string.Format("Константа.{0}", constantName));
            if (!(obj is V7Object))
            {
                return obj;
            }
            switch ((obj as V7Object).Type)
            {
                case AggregateType.Enum:
                    return new V7EnumElement((obj as V7Object));

                case AggregateType.Reference:
                    return new V7ReferenceElement((obj as V7Object), null);

                case AggregateType.Periodic:
                    return new V7PeriodicConstant((obj as V7Object));

                default:
                    return obj;
            }
        }
        public void SetConstant(string constantName, object value)
        {
            V7Object v7Object = EvalExpr("\u041A\u043E\u043D\u0441\u0442\u0430\u043D\u0442\u0430") as V7Object;
            object[] objArr = new object[] {
                                             constantName, 
                                             value };
            v7Object.InvokeMethod("\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C\u0410\u0442\u0440\u0438\u0431\u0443\u0442", objArr);
       
        }
        public V7Reference GetReference(string refName)
        {
            V7Reference v7Reference;
            V7Object v7Object;
            v7Reference = null;
            v7Object = CreateObject(string.Format("Справочник.{0}", refName));
            if (v7Object != null)
            {
                v7Reference = new V7Reference(v7Object);
            }
            return v7Reference;
        }
        public V7Document GetDocument(string docName)
        {
            V7Document v7Document = null;
            V7Object v7Object = CreateObject(String.Format("\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442.{0}", docName));
            if (v7Object != null)
                v7Document = new V7Document(v7Object);
            return v7Document;
        }
        public V7Enum GetEnumeration(string enumName)
        {
            V7Object v7Object;
            v7Object = EvalExpr(string.Format("Перечисление.{0}", enumName)) as V7Object;
            if (v7Object != null)
            {
                return new V7Enum(v7Object);
            }
            else
            {
                return null;
            }
        }
        public void BeginTransaction()
        {
            ((IComObject)this).InvokeMethod("НачатьТранзакцию", new object[0]);
        }
        public void CommitTransaction()
        {
            ((IComObject)this).InvokeMethod("ЗафиксироватьТранзакцию", new object[0]);

        }
        public void RollbackTransaction()
        {
            ((IComObject)this).InvokeMethod("ОтменитьТранзакцию", new object[0]);
        }
        internal void Activate(object comObject)
        {
            this.activeObjects.Add(comObject, comObject);
        }
        internal void Deactivate(object comObject)
        {
            if (activeObjects.ContainsKey(comObject))
                activeObjects.Remove(comObject);
       
        }
        void UmSoft.SharePoint.Integration._1Cv77.IComObject.SetProperty(string propertyName, object value)
        {
            object obj;
            Exception exception;
            if (IsConnected)
            {
                obj = value;
                if (value is V7Object)
                {
                    obj = (value as V7Object).Object;
                }
                try
                {
                    Application.GetType().InvokeMember(propertyName, BindingFlags.PutDispProperty, null, Application,
                        new object[] {
                                obj});
                }
                catch (Exception exception2)
                {
                    exception = exception2;
                    if (exception.InnerException != null)
                    {
                        throw new Exception(exception.InnerException.Message);
                    }
                    throw exception;
                }
            }
        }

        public object GetProperty(string propertyName)
        {
            if (this.IsConnected)
            {
                try
                {
                    object o = this.Application.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, this.Application, null);
                    if (((o != null) && (o is string)) && this.TrimString)
                    {
                        o = (o as string).Trim();
                    }
                    if ((o != null) && Marshal.IsComObject(o))
                    {
                        return new V7Object(o, this);
                    }
                    return o;
                }
                catch (Exception exception)
                {
                    if (exception.InnerException != null)
                    {
                        Exception exception2 = new Exception(exception.InnerException.Message);
                        throw exception2;
                    }
                    throw exception;
                }
            }
            return null;
        }

        public object InvokeMethod(string methodName, params object[] args)
        {
            return ((IComObject)this).InvokeMethod(methodName,args);
        }

        object UmSoft.SharePoint.Integration._1Cv77.IComObject.InvokeMethod(string methodName, params object[] args)
        {
            object[] arrobj;
            int i;
            object obj;
            Exception exception;
            object obj1;
            if (!IsConnected)
            {
                return null;
            }
            else
            {
                try
                {
                    arrobj = null;
                    arrobj = new object[args.Length];
                    i = 0;
                    while ((args != null) && (i < args.Length))
                    {
                        arrobj[i] = args[i] is V7Object ? (args[i] as V7Object).Object : args[i];
                        i++;
                    }
                    obj = Application.GetType().InvokeMember(methodName, BindingFlags.InvokeMethod, null, Application, arrobj);
                    if (((obj != null) && (obj is string)) && (TrimString))
                    {
                        obj = (obj as string).Trim();
                    }
                    if ((obj != null) && (Marshal.IsComObject(obj)))
                    {
                        return new V7Object(obj, this);
                    }
                    obj1 = obj;
                }
                catch (Exception exception2)
                {
                    exception = exception2;
                    if (exception.InnerException != null)
                    {
                        throw new Exception(exception.InnerException.Message);
                    }
                    throw exception;
                }
            }
            return obj1;
        }
        public void Dispose()
        {
            Disconnect();
        }
        public static double TRUE
        {
            get
            {
                return 1.0;
            }
        }
        public static double FALSE
        {
            get
            {
                return 0.0;
            }
        }
        public bool IsConnected
        {
            get
            {
                return this.isConnected;
            }
        }
        public bool IsMonopolizable
        {
            get
            {
                return ((IComObject)this).InvokeMethod("МонопольныйРежим", new object[0]).Equals(TRUE);

            }
        }
        private object Application
        {
            get
            {
                return this.application;
            }
        }
        public string Path
        {
            get
            {
                return (string)((IComObject)this).InvokeMethod("КаталогИБ", new object[0]);
            }
        }
        public string UserName
        {
            get
            {
                return (string)((IComObject)this).InvokeMethod("ИмяПользователя", new object[0]);
            }
        }
        public string RigthsSetName
        {
            get
            {
                return (string)((IComObject)this).InvokeMethod("НазваниеНабораПрав", new object[] { 0 });
            }
        }
        public string FullUserName
        {
            get
            {
                return (string)((IComObject)this).InvokeMethod("ПолноеИмяПользователя", new object[0]);

            }
        }
        private string ConnectionString
        {
            get
            {
                string s = String.Format("/D\"{0}\"", dbPath);
                if (!String.IsNullOrEmpty(userName))
                    s += String.Format(" /N{0}", userName);
                if (!String.IsNullOrEmpty(password))
                    s += String.Format(" /P{0}", password);
                return s;
            }
        }
        public bool TrimString
        {
            get
            {
                return this.trimString;
            }
            set
            {
                trimString = value;
            }
        }




        public V7Metadata Metadata
        {
            get
            {
                return new V7Metadata(this.GetProperty("Метаданные") as V7Object);
            }
        }

    }
}
